#include "ConfManager.h"

pthread_mutex_t ConfManager::_mutex = PTHREAD_MUTEX_INITIALIZER;
ConfManager *ConfManager::_instance = NULL;

ConfManager::ConfManager(std::string confFile)
{
    Configure confObj;
    if(confObj.Load(confFile) < 0)
    {
        WriteLog(FATAL, "Load configure file[%s] failed.", CONF_PATH.c_str());
        exit(-1);
    }
    WriteLog(NOTICE, "Load configure file[%s] successfully.", CONF_PATH.c_str());

    _listenPort       = confObj.GetInt("ListenPort");
    _workThreadCnt    = confObj.GetInt("WorkThreadCnt");
    _socketPoolSize   = confObj.GetInt("SocketPoolSize");
    _socketAccpetSize = confObj.GetInt("SocketAccpetSize");
    _epollTimeOut     = confObj.GetInt("EpollTimeOut");
    _keepAlive        = confObj.GetInt("KeepAlive");
    _readTimeOut      = confObj.GetInt("ReadTimeOut");
    _writeTimeOut     = confObj.GetInt("WriteTimeOut");
    _isDispatcher     = confObj.GetInt("IsDispatcher");
    _retryTime        = confObj.GetInt("RetryTime");
    if(_isDispatcher != 0)
    {
        int32 gCnt  = confObj.GetInt("GroupCnt");
        if(gCnt <= 0)
        {
            WriteLog(FATAL, "Init configure file[%s] failed, GroupNum[%d] must bigger then 0.", CONF_PATH.c_str(), gCnt);
            exit(-1);
        }
        _terminal.gCnt = gCnt;
        _terminal.group = new Group[gCnt];
        int32 sCnt = 0;
        std::string ipPort;
        char tmpBuf[256];
        for(int32 i=0; i<gCnt; i++)
        {
            snprintf(tmpBuf, sizeof(tmpBuf), "Group_%d", i);
            sCnt = confObj.GetInt(tmpBuf);
            if(sCnt <= 0)
            {
                WriteLog(FATAL, "Init configure file[%s] failed, value of %s[%d] must bigger then 0.", CONF_PATH.c_str(), tmpBuf, sCnt);
                exit(-1);
            }
            _terminal.group[i].sCnt = sCnt;
            _terminal.group[i].server = new Server[sCnt];
            for(int32 j=0; j<sCnt; j++)
            {
                snprintf(tmpBuf, sizeof(tmpBuf), "Server_%d_%d", i, j);
                ipPort = confObj.GetStr(tmpBuf);
                if(!_GetIPPort(ipPort, _terminal.group[i].server[j].ip, _terminal.group[i].server[j].port))
                {
                    WriteLog(FATAL, "Init configure file[%s] failed, value of %s[%s] is error.", CONF_PATH.c_str(), tmpBuf, ipPort.c_str());
                    exit(-1);
                }
            }
        }
    }

    WriteLog(NOTICE, "Init all configure successfully.");
}

ConfManager::~ConfManager()
{
    if(_isDispatcher != 0)
    {
        int32 gCnt  = _terminal.gCnt;
        for(int32 i=0; i<gCnt; i++)
        {
            delete [] _terminal.group[i].server;
            _terminal.group[i].server = NULL;
        }
        delete [] _terminal.group;
        _terminal.group = NULL;
    }
}

bool ConfManager::_GetIPPort(std::string ipPort, std::string &ip, int32 &port)
{
    size_t idx;
    std::string delim = "_";
    if((idx = ipPort.find(delim)) == std::string::npos)
    {
        return false;
    }

    ip   = ipPort.substr(0, idx);
    port = atoi(ipPort.substr(idx + delim.length()).c_str());

    if(ip.size() <= 0 || port <= 0)
    {
        return false;
    }

    return true;
}

ConfManager *ConfManager::Instance()
{
    if(_instance == NULL)
    {
        pthread_mutex_lock(&_mutex);

        if(_instance == NULL)
        {
            _instance = new ConfManager(CONF_PATH);
        }

        pthread_mutex_unlock(&_mutex);
    }

    return _instance;
}

int32 ConfManager::GetListenPort()
{
    return _listenPort;
}

int32 ConfManager::GetWorkThreadCnt()
{
    return _workThreadCnt;
}

int32 ConfManager::GetSocketPollSize()
{
    return _socketPoolSize;
}

int32 ConfManager::GetSocketAcceptSize()
{
    return _socketAccpetSize;
}

int32 ConfManager::GetEpollTimeOut()
{
    return _epollTimeOut;
}

int32 ConfManager::GetKeepAlive()
{
    return _keepAlive;
}

int32 ConfManager::GetReadTimeOut()
{
    return _readTimeOut;
}

int32 ConfManager::GetWriteTimeOut()
{
    return _writeTimeOut;
}

int32 ConfManager::GetIsDispatcher()
{
    return _isDispatcher;
}

int32 ConfManager::GetRetryTime()
{
    return _retryTime;
}

Terminal ConfManager::GetTerminal()
{
    return _terminal;
}
